package com.scratch.common.service.config;

import cn.hutool.core.lang.Snowflake;
import cn.hutool.core.util.IdUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.RandomUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.context.EnvironmentAware;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.env.Environment;

import java.net.Inet4Address;
import java.net.UnknownHostException;

@Configuration
@Slf4j
public class SnowflakeConfiguration implements EnvironmentAware {


    private Long workerId;
    private Long datacenterId;


    @Override
    public void setEnvironment(Environment environment) {
        this.workerId = this.getWorkId();
        this.datacenterId = this.getDataCenterId(environment.getProperty("server.port"));
        log.info("SnowflakeConfig生成workerId={},datacenterId={}", workerId, datacenterId);
    }

    @Bean("snowflake")
    public Snowflake snowflake() {
        return IdUtil.getSnowflake(workerId, datacenterId);
    }

    /**
     * workId使用IP生成
     *
     * @return workId
     */
    private Long getWorkId() {
        try {
            String hostAddress = Inet4Address.getLocalHost().getHostAddress();
            int[] ints = StringUtils.toCodePoints(hostAddress);
            int sums = 0;
            for (int b : ints) {
                sums = sums + b;
            }
            return (long) (sums % 32);
        } catch (UnknownHostException e) {
            // 失败就随机
            return RandomUtils.nextLong(0, 31);
        }
    }

    /**
     * dataCenterId使用端口号生成
     *
     * @return dataCenterId
     */
    private Long getDataCenterId(String port) {
        try {
            int[] ints = StringUtils.toCodePoints(port);
            int sums = 0;
            for (int i : ints) {
                sums = sums + i;
            }
            return (long) (sums % 32);
        } catch (Exception e) {
            // 失败就随机
            return RandomUtils.nextLong(0, 31);
        }
    }

}
